package com.etooling.pdm.controller;

import com.etooling.framework.jpa.JpaQueryBuilder;
import com.etooling.framework.jpa.Sorts;
import com.etooling.framework.jpa.Specifications;
import com.etooling.framework.svo.ReplyObj;
import com.etooling.framework.utils.WebUtils;
import com.etooling.pdm.entity.GoodsType;
import com.etooling.pdm.repository.GoodsPropValuesRepository;
import com.etooling.pdm.repository.GoodsSpecsRepository;
import com.etooling.pdm.repository.GoodsTypeRepository;
import com.etooling.pdm.service.GoodsTypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.persistence.EntityManager;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 查询产品分类控制层
 *
 * @author dyz
 * @date 2023/2/24 16:10
 * @description GoodsTypeController
 */
@RequestMapping(value = "/admin/pdm/goodsType")
@Controller
@EnableAutoConfiguration
public class GoodsTypeController {
    @Autowired
    GoodsTypeRepository goodsTypeRepository;
    @Autowired
    GoodsTypeService goodsTypeService;
    @Autowired
    GoodsSpecsRepository goodsSpecsRepository;
    @Autowired
    GoodsPropValuesRepository goodsPropValuesRepository;
    @Autowired
    EntityManager entityManager;

    /**
     * 新增分类
     * 2023/12/9
     *
     * @param request
     * @param json
     * @return
     */
    @ResponseBody
    @RequestMapping("add")
    ReplyObj add(HttpServletRequest request, @RequestParam(defaultValue = "", required = false, value = "json") String json) {
        return goodsTypeService.add(request, json);
    }


    /**
     * 修改分类
     * 2023/12/9
     *
     * @param request
     * @param json
     * @return
     */
    @ResponseBody
    @RequestMapping("update")
    ReplyObj update(HttpServletRequest request, @RequestParam(defaultValue = "", required = false, value = "json") String json) {
        return goodsTypeService.update(request, json);
    }


    @RequestMapping("updateSeq")
    @ResponseBody
    ReplyObj updateSeq(HttpServletRequest request,
                       @RequestParam(defaultValue = "", required = false, value = "parentId") String parentId,
                       @RequestParam(defaultValue = "", required = false, value = "oldSeq") Integer oldSeq,
                       @RequestParam(defaultValue = "", required = false, value = "newSeq") Integer newSeq) {
        if (!WebUtils.checkStr(parentId) || !WebUtils.checkStr(oldSeq) || !WebUtils.checkStr((newSeq))) {
            return WebUtils.flushFailure("数据异常，无法修改排序");
        }
        // 收集最大排序号
        String companyId = (String) WebUtils.getSessionValue(request, WebUtils.LOGIN_COMPANY_ID_KEY);
        Integer maxSeq = goodsTypeService.getMaxSeq(parentId, companyId);

        if (newSeq > maxSeq || newSeq < 1) {
            return WebUtils.flushFailure("序号超出已有范围");
        }
        goodsTypeRepository.updateSeq(oldSeq, newSeq, parentId, companyId);
        return WebUtils.flushSuccess("修改成功");
    }


    /**
     * 删除分类
     * 如果删除不成功，则把状态设置为删除
     *
     * @param request
     * @param vo
     * @return
     */
    @ResponseBody
    @RequestMapping("del")
    ReplyObj del(HttpServletRequest request, GoodsType vo) {
        try {
            goodsTypeRepository.delete(vo);
            return WebUtils.flushSuccess();
        } catch (Exception e) {
            e.printStackTrace();
            return WebUtils.flushFailure("产品下还有内容没有删除（可能包括：型号，型号属性配置，规格，规格属性配置），无法删除");
        }
    }


    /**
     * 获取指定所有分类
     * 2023/12/9
     *
     * @param request
     * @param parentId
     * @param isAll     用于划分是不是查询所有的分类，如果是，则查询所有的状态记录
     * @param isProduct 用于区分是产品还是物料
     * @return
     */
    @ResponseBody
    @RequestMapping("getAllType")
    ReplyObj getAllType(HttpServletRequest request,
                        @RequestParam(defaultValue = "", required = false, value = "parentId") String parentId,
                        @RequestParam(defaultValue = "false", required = false, value = "isAll") Boolean isAll,
                        @RequestParam(defaultValue = "false", required = false, value = "isProduct") Boolean isProduct) {
        JpaQueryBuilder pb = Specifications.<GoodsType>and();
        String companyId = WebUtils.getSessionValue(request, WebUtils.LOGIN_COMPANY_ID_KEY);
        pb.eq("companyId", companyId);
        if (WebUtils.checkStr(parentId)) {
            pb.eq("parentId", parentId);
        }
        if (isAll) {
            pb.ne("status", GoodsType.STATUS_IS_DEL);
        } else {
            pb.eq("status", GoodsType.STATUS_RUNNING);
        }
        if (!isProduct) {
            pb.eq("isProduct", false);
        } else {
            pb.eq("isProduct", true);
        }
        Sort sort = Sorts.builder().asc("seq").build();
        return WebUtils.flushSuccess(goodsTypeRepository.findAll(pb.build(), sort));
    }

    public static final String ROOT_ID = "root";

    /**
     * 获取分类树数据, 根绝条件 isProduct 进行获取的指定的分类树
     *
     * @param request
     * @param isProduct
     * @return
     */
    @ResponseBody
    @RequestMapping("getTypeTreeByIsProduct")
    ReplyObj getTypeTreeByIsProduct(HttpServletRequest request, @RequestParam(defaultValue = "false", required = false, value = "isProduct") Boolean isProduct) {

        String companyId = WebUtils.getSessionValue(request, WebUtils.LOGIN_COMPANY_ID_KEY);
        List<Map<String, Object>> allGoodsTypeData = goodsTypeRepository.getAllIsProductGoodsTypeData(companyId, GoodsType.STATUS_RUNNING, isProduct);

        // Repository获取到的结果是不可修改的元组类型, 需要进行复制, 复制同时进行驼峰命名转换
        List<Map<String, Object>> copiedListMap = new ArrayList<>();
        for (Map<String, Object> map : allGoodsTypeData) {
            Map<String, Object> childMap = new HashMap<>();
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                String key = entry.getKey();
                Object value = entry.getValue();
                if (key != null) {
                    // 在这里可以使用key和value进行相应的操作
                    StringBuilder result = new StringBuilder();
                    boolean nextUpperCase = false;
                    for (int i = 0; i < key.length(); i++) {
                        char currentChar = key.charAt(i);
                        if (currentChar == '_') {
                            nextUpperCase = true;
                        } else {
                            if (nextUpperCase) {
                                result.append(Character.toUpperCase(currentChar));
                                nextUpperCase = false;
                            } else {
                                result.append(Character.toLowerCase(currentChar));
                            }
                        }
                    }
                    childMap.put(result.toString(), value);
                }
            }
            copiedListMap.add(childMap);
        }

        // 按照parentId进行分组
        Map<String, List<Map<String, Object>>> groupByParentIdMap = copiedListMap.stream().collect(Collectors.groupingBy(lt -> (String) lt.get("parentId"), LinkedHashMap::new, Collectors.toList()));
        // 对每个分组中的列表中的Map按照"seq"字段进行排序
        groupByParentIdMap.forEach((key, value) -> value.sort(Comparator.comparing(m -> (Integer) m.get("seq"))));
        // 获取最顶级父类列表
        List<Map<String, Object>> rootList = groupByParentIdMap.get(ROOT_ID);
        // 处理成树结构
        handleTree(rootList, groupByParentIdMap, "", "");

        return WebUtils.flushSuccess(rootList);
    }


    /**
     * 获取所有的分类信息的分类树，不分是否为产品，是否为部件
     *
     * @param request
     * @return
     */
    @ResponseBody
    @RequestMapping("getAllTypeTree")
    ReplyObj getAllTypeTree(HttpServletRequest request) {

        String companyId = WebUtils.getSessionValue(request, WebUtils.LOGIN_COMPANY_ID_KEY);
        List<Map<String, Object>> allGoodsTypeData = goodsTypeRepository.getAllGoodsTypeData(companyId, GoodsType.STATUS_RUNNING);

        // Repository获取到的结果是不可修改的元组类型, 需要进行复制, 复制同时进行驼峰命名转换
        List<Map<String, Object>> copiedListMap = new ArrayList<>();
        for (Map<String, Object> map : allGoodsTypeData) {
            Map<String, Object> childMap = new HashMap<>();
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                String key = entry.getKey();
                Object value = entry.getValue();
                if (key != null) {
                    // 在这里可以使用key和value进行相应的操作
                    StringBuilder result = new StringBuilder();
                    boolean nextUpperCase = false;
                    for (int i = 0; i < key.length(); i++) {
                        char currentChar = key.charAt(i);
                        if (currentChar == '_') {
                            nextUpperCase = true;
                        } else {
                            if (nextUpperCase) {
                                result.append(Character.toUpperCase(currentChar));
                                nextUpperCase = false;
                            } else {
                                result.append(Character.toLowerCase(currentChar));
                            }
                        }
                    }
                    childMap.put(result.toString(), value);
                }
            }
            copiedListMap.add(childMap);
        }

        // 按照parentId进行分组
        Map<String, List<Map<String, Object>>> groupByParentIdMap = copiedListMap.stream().collect(Collectors.groupingBy(lt -> (String) lt.get("parentId"), LinkedHashMap::new, Collectors.toList()));
        // 对每个分组中的列表中的Map按照"seq"字段进行排序
        groupByParentIdMap.forEach((key, value) -> value.sort(Comparator.comparing(m -> (Integer) m.get("seq"))));
        // 获取最顶级父类列表
        List<Map<String, Object>> rootList = groupByParentIdMap.get(ROOT_ID);
        // 处理成树结构
        handleTree(rootList, groupByParentIdMap, "", "");

        return WebUtils.flushSuccess(rootList);
    }


    /**
     * 处理成树结构
     *
     * @param rootList           最顶层的父类id都root的顶层分类数据列表
     * @param groupByParentIdMap 按照父类id进行分组的 Map<String, List<Map<String, Object>>>
     * @param typeNamePath       分类名称路径，为了避免没有
     * @param typeCodePath       分类编码路径，为了避免没有
     */
    public static void handleTree(List<Map<String, Object>> rootList, Map<String, List<Map<String, Object>>> groupByParentIdMap, String typeNamePath, String typeCodePath) {
        for (Map<String, Object> map : rootList) {
            String id = (String) map.get("id");
            map.put("key", map.get("id"));
            map.put("value", map.get("id"));
            map.put("label", map.get("typeName"));
            map.put("title", map.get("typeName"));


            String namePath = (String) map.get("typeNamePath");
            if (!WebUtils.checkStr(namePath)) {
                String typeName = (String) map.get("typeName");
                if (!"".equals(typeNamePath)) {
                    typeName = typeNamePath + '-' + typeName;
                }
                namePath = typeName;
                map.put("typeNamePath", namePath);
            }

            String codePath = (String) map.get("typeCode");
            if (!WebUtils.checkStr(codePath)) {
                String typeCode = (String) map.get("typeCode");
                if (!"".equals(typeCodePath)) {
                    typeCode = typeCodePath + '-' + typeCode;
                }
                codePath = typeCode;
                map.put("typeCodePath", codePath);
            }

            if (id != null) {
                List<Map<String, Object>> childrenList = groupByParentIdMap.get(id);
                map.put("children", childrenList);
                if (childrenList != null && !childrenList.isEmpty()) {
                    handleTree(childrenList, groupByParentIdMap, namePath, codePath);
                }
            }
        }
    }


}
